home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / editors / stevie.2 < prev    next >
Text File  |  1988-12-02  |  36KB  |  1,470 lines

  1. Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i082:  stevie - vi editor clone, Part02/04
  5. Message-ID: <10420@swan.ulowell.edu>
  6. Date: 2 Dec 88 01:43:28 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 1459
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: grwalter@watcgl.waterloo.edu
  12. Posting-number: Volume 2, Issue 82
  13. Archive-name: editors/stevie.2
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    keymap.h
  23. #    linefunc.c
  24. #    macros.h
  25. #    main.c
  26. #    mark.c
  27. #    misccmds.c
  28. #    param.c
  29. #    param.h
  30. #    raw.c
  31. # This archive created: Thu Dec  1 20:37:28 1988
  32. cat << \SHAR_EOF > keymap.h
  33. /*
  34.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  35.  *
  36.  * Code Contributions By : Tim Thompson           twitch!tjt
  37.  *                         Tony Andrews           onecom!wldrdg!tony 
  38.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  39.  */
  40.  
  41. /*
  42.  * Keycode definitions for special keys 
  43.  *
  44.  * On systems that have any of these keys, the routine 'inchar' in the
  45.  * machine-dependent code should return one of the codes here. 
  46.  */
  47.  
  48. #define    K_CGRAVE    0x1e    /* control grave accent */
  49.  
  50. #define    K_HELP        0x80
  51. #define    K_UNDO        0x81
  52. #define    K_INSERT    0x82
  53. #define    K_HOME        0x83
  54. #define    K_UARROW    0x84
  55. #define    K_DARROW    0x85
  56. #define    K_LARROW    0x86
  57. #define    K_RARROW    0x87
  58. #define    K_SUARROW    0x88
  59. #define    K_SDARROW    0x89
  60. #define    K_SLARROW    0x8a
  61. #define    K_SRARROW    0x8b
  62.  
  63. #define    K_F1        0x8c    /* function keys */
  64. #define    K_F2        0x8d
  65. #define    K_F3        0x8e
  66. #define    K_F4        0x8f
  67. #define    K_F5        0x90
  68. #define    K_F6        0x91
  69. #define    K_F7        0x92
  70. #define    K_F8        0x93
  71. #define    K_F9        0x94
  72. #define    K_F10        0x95
  73.  
  74. #define    K_SF1        0x96    /* shifted function keys */
  75. #define    K_SF2        0x97
  76. #define    K_SF3        0x98
  77. #define    K_SF4        0x99
  78. #define    K_SF5        0x9a
  79. #define    K_SF6        0x9b
  80. #define    K_SF7        0x9c
  81. #define    K_SF8        0x9d
  82. #define    K_SF9        0x9e
  83. #define    K_SF10        0x9f
  84. SHAR_EOF
  85. cat << \SHAR_EOF > linefunc.c
  86. /*
  87.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  88.  *
  89.  * Code Contributions By : Tim Thompson           twitch!tjt
  90.  *                         Tony Andrews           onecom!wldrdg!tony 
  91.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  92.  */
  93.  
  94. #include "stevie.h"
  95.  
  96. /*
  97.  * nextline(curr) 
  98.  *
  99.  * Return a pointer to the beginning of the next line after the one referenced
  100.  * by 'curr'. Return NULL if there is no next line (at EOF). 
  101.  */
  102.  
  103. LPTR           *
  104. nextline(curr)
  105.     LPTR           *curr;
  106. {
  107.     static LPTR     next;
  108.  
  109.     if (curr != NULL) {
  110.     if (curr->linep->next != Fileend->linep) {
  111.         next.index = 0;
  112.         next.linep = curr->linep->next;
  113.         return &next;
  114.     }
  115.     }
  116.     return (LPTR *) NULL;
  117. }
  118.  
  119. /*
  120.  * prevline(curr) 
  121.  *
  122.  * Return a pointer to the beginning of the line before the one referenced by
  123.  * 'curr'. Return NULL if there is no prior line. 
  124.  */
  125.  
  126. LPTR           *
  127. prevline(curr)
  128.     LPTR           *curr;
  129. {
  130.     static LPTR     prev;
  131.  
  132.     if (curr != NULL) {
  133.     if (curr->linep->prev != NULL) {
  134.         prev.index = 0;
  135.         prev.linep = curr->linep->prev;
  136.         return &prev;
  137.     }
  138.     }
  139.     return (LPTR *) NULL;
  140. }
  141.  
  142. /*
  143.  * coladvance(p,col) 
  144.  *
  145.  * Try to advance to the specified column, starting at p. 
  146.  */
  147.  
  148. LPTR           *
  149. coladvance(p, col)
  150.     LPTR           *p;
  151.     int             col;
  152. {
  153.     static LPTR     lp;
  154.     int             c, in;
  155.  
  156.     lp.linep = p->linep;
  157.     lp.index = p->index;
  158.  
  159.     /* If we're on a blank ('\n' only) line, we can't do anything */
  160.     if (lp.linep->s[lp.index] == '\0')
  161.     return &lp;
  162.     /* try to advance to the specified column */
  163.     for (c = 0; col-- > 0; c++) {
  164.     /* Count a tab for what it's worth (if list mode not on) */
  165.     if (gchar(&lp) == TAB && !P(P_LS)) {
  166.         in = ((P(P_TS) - 1) - c % P(P_TS));
  167.         col -= in;
  168.         c += in;
  169.     }
  170.     /* Don't go past the end of */
  171.     /* the file or the line. */
  172.     if (inc(&lp)) {
  173.         dec(&lp);
  174.         break;
  175.     }
  176.     }
  177.     return &lp;
  178. }
  179. SHAR_EOF
  180. cat << \SHAR_EOF > macros.h
  181. /*
  182.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  183.  *
  184.  * Code Contributions By : Tim Thompson           twitch!tjt
  185.  *                         Tony Andrews           onecom!wldrdg!tony 
  186.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  187.  */
  188.  
  189. /*
  190.  * gchar(lp) - get the character at position "lp" 
  191.  */
  192. #define gchar(lp) ((lp)->linep->s[(lp)->index])
  193.  
  194. /*
  195.  * pchar(lp, c) - put character 'c' at position 'lp' 
  196.  */
  197. #define pchar(lp, c) ((lp)->linep->s[(lp)->index] = (c))
  198.  
  199. /*
  200.  * pswap(a, b) - swap two position pointers 
  201.  */
  202. #define pswap(a, b) { LPTR pswaptmp; pswaptmp = a; a = b; b = pswaptmp; }
  203.  
  204. /*
  205.  * Position comparisons 
  206.  */
  207. #define lt(a, b) ((LINEOF(a) != LINEOF(b)) \
  208.                    ? (LINEOF(a) < LINEOF(b)) : ((a)->index < (b)->index))
  209.  
  210. #define ltoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
  211.                    ? (LINEOF(a) < LINEOF(b)) : ((a)->index <= (b)->index))
  212.  
  213. #define gt(a, b) ((LINEOF(a) != LINEOF(b)) \
  214.                    ? (LINEOF(a) > LINEOF(b)) : ((a)->index > (b)->index))
  215.  
  216. #define gtoreq(a, b) ((LINEOF(a) != LINEOF(b)) \
  217.                    ? (LINEOF(a) > LINEOF(b)) : ((a)->index >= (b)->index))
  218.  
  219. #define equal(a, b) (((a)->linep == (b)->linep) && ((a)->index == (b)->index))
  220.  
  221. /*
  222.  * anyinput
  223.  *
  224.  * Return non-zero if input is pending.
  225.  */
  226. #define anyinput() (Readbuffptr != NULL)
  227.  
  228. /*
  229.  * buf1line() - return TRUE if there is only one line in file buffer
  230.  */
  231. #define buf1line() (Filemem->linep->next == Fileend->linep)
  232.  
  233. /*
  234.  * bufempty() - return TRUE if the file buffer is empty 
  235.  */
  236. #define bufempty() (buf1line() && Filemem->linep->s[0] == NUL)
  237.  
  238. /*
  239.  * lineempty() - return TRUE if the line is empty 
  240.  */
  241. #define lineempty(p) ((p)->linep->s[0] == NUL)
  242.  
  243. /*
  244.  * startofline() - return TRUE if the given position is at start of line 
  245.  */
  246. #define startofline(p) ((p)->index == 0)
  247.  
  248. /*
  249.  * endofline() - return TRUE if the given position is at end of line 
  250.  *
  251.  * This routine will probably never be called with a position resting on the NUL
  252.  * byte, but handle it correctly in case it happens. 
  253.  */
  254. #define endofline(p) \
  255.      ((p)->linep->s[(p)->index] == NUL || (p)->linep->s[(p)->index + 1] == NUL)
  256.  
  257. /*
  258.  * RowNumber() - return the row number (if no UndoInProgress)
  259.  */
  260. #define RowNumber(p) (UndoInProgress ? 0 : cntllines(Filemem, (p)))
  261. SHAR_EOF
  262. cat << \SHAR_EOF > main.c
  263. /*
  264.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  265.  *
  266.  * Code Contributions By : Tim Thompson           twitch!tjt
  267.  *                         Tony Andrews           onecom!wldrdg!tony 
  268.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  269.  */
  270.  
  271. #include "stevie.h"
  272.  
  273. int             Rows;        /* Number of Rows and Columns */
  274. int             Columns;    /* in the current window. */
  275.  
  276. char           *Realscreen = NULL;    /* What's currently on the screen, a
  277.                      * single array of size Rows*Columns. */
  278. char           *Nextscreen = NULL;    /* What's to be put on the screen. */
  279.  
  280. char           *Filename = NULL;/* Current file name */
  281.  
  282. LPTR           *Filemem;    /* The contents of the file, as a single
  283.                  * array. */
  284.  
  285. LPTR           *Fileend;    /* Pointer to the end of the file in Filemem.
  286.                  * (It points to the byte AFTER the last
  287.                  * byte.) */
  288.  
  289. LPTR           *Topchar;    /* Pointer to the byte in Filemem which is in
  290.                  * the upper left corner of the screen. */
  291.  
  292. LPTR           *Botchar;    /* Pointer to the byte in Filemem which is
  293.                  * just off the bottom of the screen. */
  294.  
  295. LPTR           *Curschar;    /* Pointer to byte in Filemem at which the
  296.                  * cursor is currently placed. */
  297.  
  298. int             Curscol;    /* Current position of cursor (column) */
  299. int             Cursrow;    /* Current position of cursor (row) */
  300.  
  301. int             Cursvcol;    /* Current virtual column, the column number
  302.                  * of the file's actual line, as opposed to
  303.                  * the column number we're at on the screen.
  304.                  * This makes a difference on lines that span
  305.                  * more than one screen line. */
  306.  
  307. int             Curswant = 0;    /* The column we'd like to be at. This is
  308.                  * used try to stay in the same column
  309.                  * through up/down cursor motions. */
  310.  
  311. bool_t          set_want_col;    /* If set, then update Curswant the next time
  312.                  * through cursupdate() to the current
  313.                  * virtual column. */
  314.  
  315. int             State = NORMAL;    /* This is the current state of the command
  316.                  * interpreter. */
  317.  
  318. int             Prenum = 0;    /* The (optional) number before a command. */
  319.  
  320. LPTR           *Insstart;    /* This is where the latest insert/append
  321.                  * mode started. */
  322.  
  323. bool_t          Changed = FALSE;/* Set to TRUE if something in the file has
  324.                  * been changed and not written out. */
  325.  
  326. char           *IObuff;        /* file reads are done, one line at a time,
  327.                  * into this buffer; as well as sprintf's */
  328.  
  329. char           *Insbuffptr = NULL;
  330. char           *Insbuff;    /* Each insertion gets stuffed into this
  331.                  * buffer. */
  332.  
  333. char           *Readbuffptr = NULL;
  334. char           *Readbuff;    /* Having this buffer allows STEVIE to easily
  335.                  * make itself do commands */
  336.  
  337. char           *Redobuffptr = NULL;
  338. char           *Redobuff;    /* Each command should stuff characters into
  339.                  * this buffer that will re-execute itself. */
  340.  
  341. bool_t          UndoInProgress = FALSE;    /* Set to TRUE if undo'ing */
  342. char           *Undobuffptr = NULL;
  343. char           *Undobuff;    /* Each command should stuff characters into
  344.                  * this buffer that will undo its effects. */
  345.  
  346. char           *UndoUndobuffptr = NULL;
  347. char           *UndoUndobuff;    /* Each command should stuff characters into
  348.                  * this buffer that will undo its undo. */
  349.  
  350. char           *Yankbuffptr = NULL;
  351. char           *Yankbuff;    /* Yank buffer */
  352.  
  353. char            last_command = NUL;    /* last command */
  354. char            last_command_char = NUL;    /* character needed to undo
  355.                          * last command */
  356.  
  357. bool_t          RedrawingDisabled = FALSE;    /* Set to TRUE if undo'ing or
  358.                          * put'ing */
  359.  
  360. bool_t          MustRedrawLine = FALSE;    /* Set to TRUE if we must redraw the
  361.                      * current line */
  362. bool_t          MustRedrawScreen = TRUE;    /* Set to TRUE if we must
  363.                          * redraw the screen */
  364.  
  365. char          **files;        /* list of input files */
  366. int             numfiles;    /* number of input files */
  367. int             curfile;    /* number of the current file */
  368.  
  369. static void
  370. usage()
  371. {
  372.     fprintf(stderr, "usage: stevie [file ...]\n");
  373.     fprintf(stderr, "       stevie -t tag\n");
  374.     fprintf(stderr, "       stevie +[num] file\n");
  375.     fprintf(stderr, "       stevie +/pat  file\n");
  376.     exit(1);
  377. }
  378.  
  379. #ifdef AMIGA
  380. void
  381. #else
  382. int
  383. #endif
  384. main(argc, argv)
  385.     int             argc;
  386.     char          **argv;
  387. {
  388.     char           *initstr, *getenv();    /* init string from the environment */
  389.     char           *tag = NULL;    /* tag from command line */
  390.     char           *pat = NULL;    /* pattern from command line */
  391.     int             line = -1;    /* line number from command line */
  392.  
  393.     int             atoi();
  394.  
  395. #ifdef AMIGA
  396. /*
  397.  * This won't be needed if you have a version of Lattice 4.01 without broken
  398.  * break signal handling.
  399.  */
  400.     (void) signal(SIGINT, SIG_IGN);
  401. #endif
  402.  
  403.     /*
  404.      * Process the command line arguments. 
  405.      */
  406.     if (argc > 1) {
  407.     switch (argv[1][0]) {
  408.  
  409.       case '-':        /* -t tag */
  410.         if (argv[1][1] != 't')
  411.         usage();
  412.  
  413.         if (argv[2] == NULL)
  414.         usage();
  415.  
  416.         Filename = NULL;
  417.         tag = argv[2];
  418.         numfiles = 1;
  419.         break;
  420.  
  421.       case '+':        /* +n or +/pat */
  422.         if (argv[1][1] == '/') {
  423.         if (argv[2] == NULL)
  424.             usage();
  425.         Filename = strsave(argv[2]);
  426.         pat = &(argv[1][1]);
  427.         numfiles = 1;
  428.  
  429.         } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
  430.         if (argv[2] == NULL)
  431.             usage();
  432.         Filename = strsave(argv[2]);
  433.         numfiles = 1;
  434.  
  435.         line = (isdigit(argv[1][1])) ?
  436.             atoi(&(argv[1][1])) : 0;
  437.         } else
  438.         usage();
  439.  
  440.         break;
  441.  
  442.       default:        /* must be a file name */
  443.         Filename = strsave(argv[1]);
  444.         files = &(argv[1]);
  445.         numfiles = argc - 1;
  446.         break;
  447.     }
  448.     } else {
  449.     Filename = NULL;
  450.     numfiles = 1;
  451.     }
  452.     curfile = 0;
  453.  
  454.     windinit();
  455.  
  456.     /*
  457.      * Allocate LPTR structures for all the various position pointers 
  458.      */
  459.     if ((Filemem = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  460.     fprintf(stderr, "Can't allocate data structures\n");
  461.     windexit(0);
  462.     }
  463.     if ((Fileend = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  464.     fprintf(stderr, "Can't allocate data structures\n");
  465.     windexit(0);
  466.     }
  467.     if ((Topchar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  468.     fprintf(stderr, "Can't allocate data structures\n");
  469.     windexit(0);
  470.     }
  471.     if ((Botchar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  472.     fprintf(stderr, "Can't allocate data structures\n");
  473.     windexit(0);
  474.     }
  475.     if ((Curschar = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  476.     fprintf(stderr, "Can't allocate data structures\n");
  477.     windexit(0);
  478.     }
  479.     if ((Insstart = (LPTR *) malloc((unsigned) sizeof(LPTR))) == NULL) {
  480.     fprintf(stderr, "Can't allocate data structures\n");
  481.     windexit(0);
  482.     }
  483.     /*
  484.      * Allocate space for the many buffers 
  485.      */
  486.     if ((IObuff = malloc(IOSIZE)) == NULL) {
  487.     fprintf(stderr, "Can't allocate data structures\n");
  488.     windexit(0);
  489.     }
  490.     if ((Insbuff = malloc(INSERT_SIZE)) == NULL) {
  491.     fprintf(stderr, "Can't allocate data structures\n");
  492.     windexit(0);
  493.     }
  494.     if ((Readbuff = malloc(READSIZE)) == NULL) {
  495.     fprintf(stderr, "Can't allocate data structures\n");
  496.     windexit(0);
  497.     }
  498.     if ((Redobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
  499.     fprintf(stderr, "Can't allocate data structures\n");
  500.     windexit(0);
  501.     }
  502.     if ((Undobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
  503.     fprintf(stderr, "Can't allocate data structures\n");
  504.     windexit(0);
  505.     }
  506.     if ((UndoUndobuff = malloc(REDO_UNDO_SIZE)) == NULL) {
  507.     fprintf(stderr, "Can't allocate data structures\n");
  508.     windexit(0);
  509.     }
  510.     if ((Yankbuff = malloc(YANKSIZE)) == NULL) {
  511.     fprintf(stderr, "Can't allocate data structures\n");
  512.     windexit(0);
  513.     }
  514.     screenalloc();
  515.     filealloc();        /* Initialize Filemem & Fileend */
  516.  
  517.     screenclear();
  518.  
  519.     if ((initstr = getenv("EXINIT")) != NULL) {
  520.     char           *lp, buf[128];
  521.  
  522.     if ((lp = getenv("LINES")) != NULL) {
  523.         sprintf(buf, "%s lines=%s", initstr, lp);
  524.         readcmdline(':', buf);
  525.     } else
  526.         readcmdline(':', initstr);
  527.     }
  528.     if (Filename != NULL) {
  529.     if (readfile(Filename, Filemem, FALSE))
  530.         filemess("[New File]");
  531.     } else
  532.     msg("Empty Buffer");
  533.  
  534.     setpcmark();
  535.  
  536.     updateNextscreen();
  537.  
  538.     if (tag) {
  539.     stuffReadbuff(":ta ");
  540.     stuffReadbuff(tag);
  541.     stuffReadbuff("\n");
  542.  
  543.     } else if (pat) {
  544.     stuffReadbuff(pat);
  545.     stuffReadbuff("\n");
  546.  
  547.     } else if (line >= 0) {
  548.     if (line > 0)
  549.         stuffnumReadbuff(line);
  550.     stuffReadbuff("G");
  551.     }
  552.     edit();
  553.  
  554.     windexit(0);
  555. }
  556.  
  557. void
  558. stuffReadbuff(s)
  559.     char           *s;
  560. {
  561.     if (strlen(s) == 0)
  562.     return;
  563.  
  564.     if (Readbuffptr == NULL) {
  565.     if ((strlen(s) + 1) < READSIZE) {
  566.         strcpy(Readbuff, s);
  567.         Readbuffptr = Readbuff;
  568.     } else
  569.         emsg("Couldn't stuffReadbuff() - should never happen");
  570.     } else if ((strlen(Readbuff) + (strlen(s) + 1)) < READSIZE)
  571.     strcat(Readbuff, s);
  572.     else
  573.     emsg("Couldn't stuffReadbuff() - should never happen");
  574. }
  575.  
  576. void
  577. stuffnumReadbuff(n)
  578.     int             n;
  579. {
  580.     char            buf[32];
  581.  
  582.     sprintf(buf, "%d", n);
  583.     stuffReadbuff(buf);
  584. }
  585.  
  586. /* OPTRESULT */
  587. char
  588. vgetc()
  589. {
  590.     if (Readbuffptr != NULL) {
  591.     char            nextc = *Readbuffptr++;
  592.     if (*Readbuffptr == NUL) {
  593.         *Readbuff = NUL;
  594.         Readbuffptr = NULL;
  595.     }
  596.     return (nextc);
  597.     }
  598.     return (inchar());
  599. }
  600.  
  601. char
  602. vpeekc()
  603. {
  604.     if (Readbuffptr != NULL)
  605.     return (*Readbuffptr);
  606.     return (NUL);
  607. }
  608. SHAR_EOF
  609. cat << \SHAR_EOF > mark.c
  610. /*
  611.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  612.  *
  613.  * Code Contributions By : Tim Thompson           twitch!tjt
  614.  *                         Tony Andrews           onecom!wldrdg!tony 
  615.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  616.  */
  617.  
  618. #include "stevie.h"
  619.  
  620. #ifdef    MEGAMAX
  621. overlay "mark"
  622. #endif
  623.  
  624. /*
  625.  * This file contains routines to maintain and manipulate marks. 
  626.  */
  627.  
  628. #define    NMARKS    10        /* max. # of marks that can be saved */
  629.  
  630. struct mark {
  631.     char            name;
  632.     LPTR            pos;
  633. };
  634.  
  635. static struct mark mlist[NMARKS];
  636. static struct mark pcmark;    /* previous context mark */
  637. static bool_t   pcvalid = FALSE;/* true if pcmark is valid */
  638.  
  639. /*
  640.  * setmark(c) - set mark 'c' at current cursor position 
  641.  *
  642.  * Returns TRUE on success, FALSE if no room for mark or bad name given. 
  643.  */
  644. bool_t
  645. setmark(c)
  646.     char            c;
  647. {
  648.     int             i;
  649.  
  650.     if (!isalpha(c))
  651.     return FALSE;
  652.  
  653.     /*
  654.      * If there is already a mark of this name, then just use the existing
  655.      * mark entry. 
  656.      */
  657.     for (i = 0; i < NMARKS; i++) {
  658.     if (mlist[i].name == c) {
  659.         mlist[i].pos = *Curschar;
  660.         return TRUE;
  661.     }
  662.     }
  663.  
  664.     /*
  665.      * There wasn't a mark of the given name, so find a free slot 
  666.      */
  667.     for (i = 0; i < NMARKS; i++) {
  668.     if (mlist[i].name == NUL) {    /* got a free one */
  669.         mlist[i].name = c;
  670.         mlist[i].pos = *Curschar;
  671.         return TRUE;
  672.     }
  673.     }
  674.     return FALSE;
  675. }
  676.  
  677. /*
  678.  * setpcmark() - set the previous context mark to the current position 
  679.  */
  680. void
  681. setpcmark()
  682. {
  683.     pcmark.pos = *Curschar;
  684.     pcvalid = TRUE;
  685. }
  686.  
  687. /*
  688.  * getmark(c) - find mark for char 'c' 
  689.  *
  690.  * Return pointer to LPTR or NULL if no such mark. 
  691.  */
  692. LPTR           *
  693. getmark(c)
  694.     char            c;
  695. {
  696.     int             i;
  697.  
  698.     if (c == '\'' || c == '`')    /* previous context mark */
  699.     return pcvalid ? &(pcmark.pos) : (LPTR *) NULL;
  700.  
  701.     for (i = 0; i < NMARKS; i++) {
  702.     if (mlist[i].name == c)
  703.         return &(mlist[i].pos);
  704.     }
  705.     return (LPTR *) NULL;
  706. }
  707.  
  708. /*
  709.  * clrall() - clear all marks 
  710.  *
  711.  * Used mainly when trashing the entire buffer during ":e" type commands 
  712.  */
  713. void
  714. clrall()
  715. {
  716.     int             i;
  717.  
  718.     for (i = 0; i < NMARKS; i++)
  719.     mlist[i].name = NUL;
  720.     pcvalid = FALSE;
  721. }
  722.  
  723. /*
  724.  * clrmark(line) - clear any marks for 'line' 
  725.  *
  726.  * Used any time a line is deleted so we don't have marks pointing to
  727.  * non-existent lines. 
  728.  */
  729. void
  730. clrmark(line)
  731.     LINE           *line;
  732. {
  733.     int             i;
  734.  
  735.     for (i = 0; i < NMARKS; i++) {
  736.     if (mlist[i].pos.linep == line)
  737.         mlist[i].name = NUL;
  738.     }
  739.     if (pcvalid && (pcmark.pos.linep == line))
  740.     pcvalid = FALSE;
  741. }
  742. SHAR_EOF
  743. cat << \SHAR_EOF > misccmds.c
  744. /*
  745.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  746.  *
  747.  * Code Contributions By : Tim Thompson           twitch!tjt
  748.  *                         Tony Andrews           onecom!wldrdg!tony 
  749.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  750.  */
  751.  
  752. #include "stevie.h"
  753.  
  754. static          bool_t
  755. openfwd(), openbwd();
  756.  
  757. extern int      did_ai;
  758.  
  759. /*
  760.  * opencmd 
  761.  *
  762.  * Add a blank line above or below the current line. 
  763.  */
  764.  
  765. bool_t
  766. opencmd(dir, can_ai)
  767.     int             dir;
  768.     int             can_ai;    /* if true, consider auto-indent */
  769. {
  770.     if (dir == FORWARD)
  771.     return (openfwd(can_ai));
  772.     else
  773.     return (openbwd(can_ai));
  774. }
  775.  
  776. static          bool_t
  777. openfwd(can_ai)
  778.     int             can_ai;
  779. {
  780.     LINE           *l;
  781.     LPTR           *next;
  782.     char           *s;        /* string to be moved to new line, if any */
  783.  
  784.     /*
  785.      * If we're in insert mode, we need to move the remainder of the current
  786.      * line onto the new line. Otherwise the new line is left blank. 
  787.      */
  788.     if (State == INSERT)
  789.     s = &Curschar->linep->s[Curschar->index];
  790.     else
  791.     s = "";
  792.  
  793.     if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  794.     next = Fileend;
  795.  
  796.     /*
  797.      * By asking for as much space as the prior line had we make sure that
  798.      * we'll have enough space for any auto-indenting. 
  799.      */
  800.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
  801.     emsg("out of memory");
  802.     beep();
  803.     sleep(2);
  804.     return (FALSE);
  805.     }
  806.     if (*s != NUL)
  807.     strcpy(l->s, s);    /* copy string to new line */
  808. #ifdef AUTO_INDENT
  809.     else if (can_ai && P(P_AI)) {
  810.     /*
  811.      * Auto-indent removed due to buggy implementation... 
  812.      */
  813.     did_ai = TRUE;
  814.     }
  815. #endif
  816.  
  817.     if (State == INSERT)    /* truncate current line at cursor */
  818.     *s = NUL;
  819.  
  820.     Curschar->linep->next = l;    /* link neighbors to new line */
  821.     next->linep->prev = l;
  822.  
  823.     l->prev = Curschar->linep;    /* link new line to neighbors */
  824.     l->next = next->linep;
  825.  
  826.     if (next == Fileend)    /* new line at end */
  827.     l->num = Curschar->linep->num + LINEINC;
  828.  
  829.     else if ((l->prev->num) + 1 == l->next->num)    /* no gap, renumber */
  830.     renum();
  831.  
  832.     else {            /* stick it in the middle */
  833.     long            lnum;
  834.     lnum = (l->prev->num + l->next->num) / 2;
  835.     l->num = lnum;
  836.     }
  837.  
  838.     *Curschar = *nextline(Curschar);    /* cursor moves down */
  839.     Curschar->index = 0;
  840.  
  841.     s_ins(Cursrow + 1, 1);    /* insert a physical line */
  842.     updateNextscreen();        /* because Botchar is now invalid */
  843.     cursupdate();        /* update Cursrow before insert */
  844.  
  845.     return (TRUE);
  846. }
  847.  
  848. static          bool_t
  849. openbwd(can_ai)
  850.     int             can_ai;
  851. {
  852.     LINE           *l;
  853.     LPTR           *prev;
  854.  
  855.     prev = prevline(Curschar);
  856.  
  857.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
  858.     emsg("out of memory");
  859.     beep();
  860.     sleep(2);
  861.     return (FALSE);
  862.     }
  863.     Curschar->linep->prev = l;    /* link neighbors to new line */
  864.     if (prev != NULL)
  865.     prev->linep->next = l;
  866.  
  867.     l->next = Curschar->linep;    /* link new line to neighbors */
  868.     if (prev != NULL)
  869.     l->prev = prev->linep;
  870.  
  871. #ifdef AUTO_INDENT
  872.     if (can_ai && P(P_AI)) {
  873.     /*
  874.      * Auto-indent removed due to buggy implementation... 
  875.      */
  876.     did_ai = TRUE;
  877.     }
  878. #endif
  879.  
  880.     *Curschar = *prevline(Curschar);    /* cursor moves up */
  881.     Curschar->index = 0;
  882.  
  883.     if (prev == NULL)        /* new start of file */
  884.     Filemem->linep = l;
  885.  
  886.     renum();            /* keep it simple - we don't do this often */
  887.  
  888.     cursupdate();        /* update Cursrow before insert */
  889.     if (Cursrow != 0)
  890.     s_ins(Cursrow, 1);    /* insert a physical line */
  891.     updateNextscreen();
  892.  
  893.     return (TRUE);
  894. }
  895.  
  896. int
  897. cntllines(pbegin, pend)
  898.     LPTR           *pbegin, *pend;
  899. {
  900.     register LINE  *lp;
  901.     register int    lnum = 1;
  902.  
  903.     for (lp = pbegin->linep; lp != pend->linep; lp = lp->next)
  904.     lnum++;
  905.  
  906.     return (lnum);
  907. }
  908.  
  909. /*
  910.  * plines(p) - return the number of physical screen lines taken by line 'p' 
  911.  */
  912. int
  913. plines(p)
  914.     LPTR           *p;
  915. {
  916.     int             col;
  917.     char           *s;
  918.  
  919.     if (p == NULL) {
  920.     fprintf(stderr, "plines(p) : p == NULL ????");
  921.     return (0);
  922.     }
  923.     s = p->linep->s;
  924.  
  925.     if (*s == NUL)        /* empty line */
  926.     return 1;
  927.  
  928.     /*
  929.      * If list mode is on, then the '$' at the end of the line takes up one
  930.      * extra column. 
  931.      */
  932.     col = P(P_LS) ? 1 : 0;
  933.  
  934.     for (; *s != NUL; s++) {
  935.     if (*s == TAB && !P(P_LS))
  936.         col += P(P_TS) - (col % P(P_TS));
  937.     else
  938.         col += chars[*s].ch_size;
  939.     }
  940.     return ((col + (Columns - 1)) / Columns);
  941. }
  942.  
  943. void
  944. fileinfo()
  945. {
  946.     long            l1, l2;
  947.     char            buf[MAX_COLUMNS + 1];
  948.  
  949.     if (bufempty()) {
  950.     msg("Buffer Empty");
  951.     return;
  952.     }
  953.     l1 = cntllines(Filemem, Curschar);
  954.     l2 = cntllines(Filemem, Fileend) - 1;
  955.     sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
  956.         (Filename != NULL) ? Filename : "No File",
  957.         Changed ? " [Modified]" : "",
  958.         l1, l2, (l1 * 100) / l2);
  959.     msg(buf);
  960. }
  961.  
  962. /*
  963.  * gotoline(n) - return a pointer to line 'n' 
  964.  *
  965.  * Returns a pointer to the last line of the file if n is zero, or beyond the
  966.  * end of the file. 
  967.  */
  968. LPTR           *
  969. gotoline(n)
  970.     int             n;
  971. {
  972.     static LPTR     l;
  973.  
  974.     l.index = 0;
  975.  
  976.     if (n == 0)
  977.     l = *prevline(Fileend);
  978.     else {
  979.     LPTR           *p;
  980.  
  981.     for (l = *Filemem; --n > 0; l = *p)
  982.         if ((p = nextline(&l)) == NULL)
  983.         break;
  984.     }
  985.     return &l;
  986. }
  987.  
  988. void
  989. inschar(c)
  990.     char            c;
  991. {
  992.     char           *p;
  993.     char           *pend;
  994.  
  995.     /* make room for the new char. */
  996.     if (!canincrease(1))
  997.     return;
  998.  
  999.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  1000.     pend = &Curschar->linep->s[Curschar->index];
  1001.  
  1002.     for (; p > pend; p--)
  1003.     *p = *(p - 1);
  1004.  
  1005.     *p = c;
  1006.  
  1007.     if (RedrawingDisabled) {
  1008.     inc(Curschar);
  1009.     return;
  1010.     }
  1011.     /*
  1012.      * If we're in insert mode and showmatch mode is set, then check for
  1013.      * right parens and braces. If there isn't a match, then beep. If there
  1014.      * is a match AND it's on the screen, then flash to it briefly. If it
  1015.      * isn't on the screen, don't do anything. 
  1016.      */
  1017.     if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  1018.     LPTR           *lpos, csave;
  1019.  
  1020.     if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  1021.         beep();
  1022.     else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  1023.         updateNextscreen();    /* show the new char first */
  1024.         updateRealscreen();
  1025.         csave = *Curschar;
  1026.         *Curschar = *lpos;    /* move to matching char */
  1027.         cursupdate();
  1028.         windgoto(Cursrow, Curscol);
  1029.         delay();        /* brief pause */
  1030.         *Curschar = csave;    /* restore cursor position */
  1031.         cursupdate();
  1032.     }
  1033.     }
  1034.     inc(Curschar);
  1035. }
  1036.  
  1037. void
  1038. insstr(s)
  1039.     char           *s;
  1040. {
  1041.     char           *p, *endp;
  1042.     int             k, n = strlen(s);
  1043.  
  1044.     /* Move everything in the file over to make */
  1045.     /* room for the new string. */
  1046.     if (!canincrease(n))
  1047.     return;
  1048.  
  1049.     endp = &Curschar->linep->s[Curschar->index];
  1050.     p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
  1051.  
  1052.     for (; p > endp; p--)
  1053.     *p = *(p - n);
  1054.  
  1055.     p = &Curschar->linep->s[Curschar->index];
  1056.     for (k = 0; k < n; k++) {
  1057.     *p++ = *s++;
  1058.     inc(Curschar);
  1059.     }
  1060. }
  1061.  
  1062. bool_t
  1063. delchar(fixpos, undo)
  1064.     bool_t          fixpos;    /* if TRUE fix the cursor position when done */
  1065.     bool_t          undo;    /* if TRUE put char deleted into Undo buffer */
  1066. {
  1067.     int             i;
  1068.  
  1069.     /* Check for degenerate case; there's nothing in the file. */
  1070.     if (bufempty())
  1071.     return FALSE;
  1072.  
  1073.     if (lineempty(Curschar))    /* can't do anything */
  1074.     return FALSE;
  1075.  
  1076.     if (undo)
  1077.     AppendToUndobuff(mkstr(gchar(Curschar)));
  1078.  
  1079.     /* Delete the char. at Curschar by shifting everything in the line down. */
  1080.     for (i = Curschar->index + 1; i < Curschar->linep->size; i++)
  1081.     Curschar->linep->s[i - 1] = Curschar->linep->s[i];
  1082.  
  1083.     /*
  1084.      * If we just took off the last character of a non-blank line, we don't
  1085.      * want to end up positioned at the newline. 
  1086.      */
  1087.     if (fixpos) {
  1088.     if (gchar(Curschar) == NUL && Curschar->index > 0 && State != INSERT)
  1089.         Curschar->index--;
  1090.     }
  1091.     return TRUE;
  1092. }
  1093.  
  1094. void
  1095. delline(nlines)
  1096. {
  1097.     LINE           *p, *q;
  1098.     int             doscreen = TRUE;    /* if true, update the screen */
  1099.  
  1100.     /*
  1101.      * There's no point in keeping the screen updated if we're deleting more
  1102.      * than a screen's worth of lines. 
  1103.      */
  1104.     if (nlines > (Rows - 1)) {
  1105.     doscreen = FALSE;
  1106.     s_del(Cursrow, Rows - 1);    /* flaky way to clear rest of screen */
  1107.     }
  1108.     while (nlines-- > 0) {
  1109.  
  1110.     if (bufempty())        /* nothing to delete */
  1111.         break;
  1112.  
  1113.     if (buf1line()) {    /* just clear the line */
  1114.         Curschar->linep->s[0] = NUL;
  1115.         Curschar->index = 0;
  1116.         break;
  1117.     }
  1118.     p = Curschar->linep->prev;
  1119.     q = Curschar->linep->next;
  1120.  
  1121.     if (p == NULL) {    /* first line of file so... */
  1122.         Filemem->linep = q;    /* adjust start of file */
  1123.         Topchar->linep = q;    /* and screen */
  1124.     } else
  1125.         p->next = q;
  1126.     q->prev = p;
  1127.  
  1128.     clrmark(Curschar->linep);    /* clear marks for the line */
  1129.  
  1130.     /*
  1131.      * Delete the correct number of physical lines on the screen 
  1132.      */
  1133.     if (doscreen)
  1134.         s_del(Cursrow, plines(Curschar));
  1135.  
  1136.     /*
  1137.      * If deleting the top line on the screen, adjust Topchar 
  1138.      */
  1139.     if (Topchar->linep == Curschar->linep)
  1140.         Topchar->linep = q;
  1141.  
  1142.     free(Curschar->linep->s);
  1143.     free((char *) (Curschar->linep));
  1144.  
  1145.     Curschar->linep = q;
  1146.     Curschar->index = 0;    /* is this right? */
  1147.  
  1148.     /* If we delete the last line in the file, back up */
  1149.     if (Curschar->linep == Fileend->linep) {
  1150.         Curschar->linep = Curschar->linep->prev;
  1151.         /* and don't try to delete any more lines */
  1152.         break;
  1153.     }
  1154.     }
  1155. }
  1156. SHAR_EOF
  1157. cat << \SHAR_EOF > param.c
  1158. /*
  1159.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1160.  *
  1161.  * Code Contributions By : Tim Thompson           twitch!tjt
  1162.  *                         Tony Andrews           onecom!wldrdg!tony 
  1163.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1164.  */
  1165.  
  1166. /*
  1167.  * Code to handle user-settable parameters. This is all pretty much table-
  1168.  * driven. To add a new parameter, put it in the params array, and add a
  1169.  * macro for it in param.h. If it's a numeric parameter, add any necessary
  1170.  * bounds checks to doset(). String parameters aren't currently supported. 
  1171.  */
  1172.  
  1173. #include "stevie.h"
  1174.  
  1175. struct param    params[] = {
  1176.  
  1177.                 {"tabstop", "ts", 8, P_NUM},
  1178.                 {"scroll", "scroll", 12, P_NUM},
  1179.                 {"report", "report", 5, P_NUM},
  1180.                 {"lines", "lines", 25, P_NUM},
  1181.  
  1182.                 {"vbell", "vb", TRUE, P_BOOL},
  1183.                 {"showmatch", "sm", FALSE, P_BOOL},
  1184.                 {"wrapscan", "ws", TRUE, P_BOOL},
  1185.                 {"errorbells", "eb", FALSE, P_BOOL},
  1186.                 {"showmode", "mo", FALSE, P_BOOL},
  1187.                 {"backup", "bk", FALSE, P_BOOL},
  1188.                 {"return", "cr", TRUE, P_BOOL},
  1189.                 {"list", "list", FALSE, P_BOOL},
  1190.                 {"autoindent", "ai", FALSE, P_BOOL},
  1191.  
  1192.                 {"", "", 0, 0,}    /* end marker */
  1193. };
  1194.  
  1195. static void     showparms();
  1196.  
  1197. void
  1198. doset(arg, inter)
  1199.     char           *arg;    /* parameter string */
  1200.     bool_t          inter;    /* TRUE if called interactively */
  1201. {
  1202.     int             i;
  1203.     char           *s;
  1204.     bool_t          did_lines = FALSE;
  1205.  
  1206.     bool_t          state = TRUE;    /* new state of boolean parms. */
  1207.  
  1208.     if (arg == NULL) {
  1209.     showparms(FALSE);
  1210.     return;
  1211.     }
  1212.     if (strncmp(arg, "all", 3) == 0) {
  1213.     showparms(TRUE);
  1214.     return;
  1215.     }
  1216.     if (strncmp(arg, "no", 2) == 0) {
  1217.     state = FALSE;
  1218.     arg += 2;
  1219.     }
  1220.     for (i = 0; params[i].fullname[0] != NUL; i++) {
  1221.     s = params[i].fullname;
  1222.     if (strncmp(arg, s, strlen(s)) == 0)    /* matched full name */
  1223.         break;
  1224.     s = params[i].shortname;
  1225.     if (strncmp(arg, s, strlen(s)) == 0)    /* matched short name */
  1226.         break;
  1227.     }
  1228.  
  1229.     if (params[i].fullname[0] != NUL) {    /* found a match */
  1230.     if (params[i].flags & P_NUM) {
  1231.         did_lines = (i == P_LI);
  1232.         if (inter && (arg[strlen(s)] != '=' || state == FALSE))
  1233.         emsg("Invalid set of numeric parameter");
  1234.         else {
  1235.         params[i].value = atoi(arg + strlen(s) + 1);
  1236.         params[i].flags |= P_CHANGED;
  1237.         }
  1238.     } else {        /* boolean */
  1239.         if (inter && (arg[strlen(s)] == '='))
  1240.         emsg("Invalid set of boolean parameter");
  1241.         else {
  1242.         params[i].value = state;
  1243.         params[i].flags |= P_CHANGED;
  1244.         }
  1245.     }
  1246.     } else {
  1247.     if (inter)
  1248.         emsg("Unrecognized 'set' option");
  1249.     }
  1250.  
  1251.     /*
  1252.      * Update the screen in case we changed something like "tabstop" or
  1253.      * "list" that will change its appearance. 
  1254.      */
  1255.     if (inter)
  1256.     updateNextscreen();
  1257.  
  1258.     if (did_lines) {
  1259.     Rows = P(P_LI);
  1260.     screenalloc();        /* allocate new screen buffers */
  1261.     screenclear();
  1262.     updateNextscreen();
  1263.     }
  1264.     /*
  1265.      * Check the bounds for numeric parameters here 
  1266.      */
  1267.     if (P(P_TS) <= 0 || P(P_TS) > 32) {
  1268.     if (inter)
  1269.         emsg("Invalid tab size specified");
  1270.     P(P_TS) = 8;
  1271.     return;
  1272.     }
  1273.     if (P(P_SS) <= 0 || P(P_SS) > Rows) {
  1274.     if (inter)
  1275.         emsg("Invalid scroll size specified");
  1276.     P(P_SS) = 12;
  1277.     return;
  1278.     }
  1279.     /*
  1280.      * Check for another argument, and call doset() recursively, if found. If
  1281.      * any argument results in an error, no further parameters are processed. 
  1282.      */
  1283.     while (*arg != ' ' && *arg != '\t') {    /* skip to next white space */
  1284.     if (*arg == NUL)
  1285.         return;        /* end of parameter list */
  1286.     arg++;
  1287.     }
  1288.     while (*arg == ' ' || *arg == '\t')    /* skip to next non-white */
  1289.     arg++;
  1290.  
  1291.     if (*arg)
  1292.     doset(arg, TRUE);    /* recurse on next parameter, if present */
  1293. }
  1294.  
  1295. static void
  1296. showparms(all)
  1297.     bool_t          all;    /* show ALL parameters */
  1298. {
  1299.     struct param   *p;
  1300.     char            buf[64];
  1301.  
  1302.     gotocmdline(YES, NUL);
  1303.     outstr("Parameters:\r\n");
  1304.  
  1305.     for (p = ¶ms[0]; p->fullname[0] != NUL; p++) {
  1306.     if (!all && ((p->flags & P_CHANGED) == 0))
  1307.         continue;
  1308.     if (p->flags & P_BOOL)
  1309.         sprintf(buf, "\t%s%s\r\n",
  1310.             (p->value ? "" : "no"), p->fullname);
  1311.     else
  1312.         sprintf(buf, "\t%s=%d\r\n", p->fullname, p->value);
  1313.  
  1314.     outstr(buf);
  1315.     }
  1316.     wait_return();
  1317. }
  1318. SHAR_EOF
  1319. cat << \SHAR_EOF > param.h
  1320. /*
  1321.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1322.  *
  1323.  * Code Contributions By : Tim Thompson           twitch!tjt
  1324.  *                         Tony Andrews           onecom!wldrdg!tony 
  1325.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1326.  */
  1327.  
  1328. /*
  1329.  * Settable parameters 
  1330.  */
  1331.  
  1332. struct param {
  1333.     char           *fullname;    /* full parameter name */
  1334.     char           *shortname;    /* permissible abbreviation */
  1335.     int             value;    /* parameter value */
  1336.     int             flags;
  1337. };
  1338.  
  1339. extern struct param params[];
  1340.  
  1341. /*
  1342.  * Flags 
  1343.  */
  1344. #define    P_BOOL        0x01    /* the parameter is boolean */
  1345. #define    P_NUM        0x02    /* the parameter is numeric */
  1346. #define    P_CHANGED    0x04    /* the parameter has been changed */
  1347.  
  1348. /*
  1349.  * The following are the indices in the params array for each parameter 
  1350.  */
  1351.  
  1352. /*
  1353.  * Numeric parameters 
  1354.  */
  1355. #define    P_TS        0    /* tab size */
  1356. #define    P_SS        1    /* scroll size */
  1357. #define    P_RP        2    /* report */
  1358. #define    P_LI        3    /* lines */
  1359.  
  1360. /*
  1361.  * Boolean parameters 
  1362.  */
  1363. #define    P_VB        4    /* visual bell */
  1364. #define    P_SM        5    /* showmatch */
  1365. #define    P_WS        6    /* wrap scan */
  1366. #define    P_EB        7    /* error bells */
  1367. #define    P_MO        8    /* show mode */
  1368. #define    P_BK        9    /* make backups when writing out files */
  1369. #define    P_CR        10    /* use cr-lf to terminate lines on writes */
  1370. #define    P_LS        11    /* show tabs and newlines graphically */
  1371.  
  1372. #define    P_AI        12    /* auto-indent */
  1373.  
  1374. /*
  1375.  * Macro to get the value of a parameter 
  1376.  */
  1377. #define    P(n)    (params[n].value)
  1378. SHAR_EOF
  1379. cat << \SHAR_EOF > raw.c
  1380. /*
  1381.  * raw.c 
  1382.  *
  1383.  * This is a routine for setting a given stream to raw or cooked mode on the
  1384.  * Amiga . This is useful when you are using Lattice C to produce programs
  1385.  * that want to read single characters with the "getch()" or "fgetc" call. 
  1386.  *
  1387.  * Written : 18-Jun-87 By Chuck McManis.
  1388.  */
  1389. #include <exec/types.h>
  1390. #include <libraries/dos.h>
  1391. #include <libraries/dosextens.h>
  1392. #include <stdio.h>
  1393. #include <ios1.h>
  1394. #include <error.h>
  1395.  
  1396. extern int      errno;        /* The error variable */
  1397.  
  1398. /*
  1399.  * Function raw() - Convert the specified file pointer to 'raw' mode. This
  1400.  * only works on TTY's and essentially keeps DOS from translating keys for
  1401.  * you, also (BIG WIN) it means getch() will return immediately rather than
  1402.  * wait for a return. You lose editing features though. 
  1403.  */
  1404. long
  1405. raw(fp)
  1406.     FILE           *fp;
  1407.  
  1408. {
  1409.     struct MsgPort *mp;        /* The File Handle message port */
  1410.     struct FileHandle *afh;
  1411.     struct UFB     *ufb;
  1412.     long            Arg[1], res;
  1413.  
  1414.     ufb = (struct UFB *) chkufb(fileno(fp));    /* Step one, get the file
  1415.                          * handle */
  1416.     afh = (struct FileHandle *) (ufb->ufbfh);
  1417.  
  1418.     if (!IsInteractive(afh)) {    /* Step two, check to see if it's a console */
  1419.     errno = ENOTTY;
  1420.     return (-1);
  1421.     }
  1422.     /* Step three, get it's message port. */
  1423.     mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
  1424.     Arg[0] = -1L;
  1425.     res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1);    /* Put it in RAW: mode */
  1426.     if (res == 0) {
  1427.     errno = ENXIO;
  1428.     return (-1);
  1429.     }
  1430.     return (0);
  1431. }
  1432.  
  1433. /*
  1434.  * Function - cooked() this function returns the designate file pointer to
  1435.  * it's normal, wait for a <CR> mode. This is exactly like raw() except that
  1436.  * it sends a 0 to the console to make it back into a CON: from a RAW: 
  1437.  */
  1438.  
  1439. long
  1440. cooked(fp)
  1441.     FILE           *fp;
  1442.  
  1443. {
  1444.     struct MsgPort *mp;        /* The File Handle message port */
  1445.     struct FileHandle *afh;
  1446.     struct UFB     *ufb;
  1447.     long            Arg[1], res;
  1448.  
  1449.     ufb = (struct UFB *) chkufb(fileno(fp));
  1450.     afh = (struct FileHandle *) (ufb->ufbfh);
  1451.     if (!IsInteractive(afh)) {
  1452.     errno = ENOTTY;
  1453.     return (-1);
  1454.     }
  1455.     mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
  1456.     Arg[0] = 0;
  1457.     res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1);
  1458.     if (res == 0) {
  1459.     errno = ENXIO;
  1460.     return (-1);
  1461.     }
  1462.     return (0);
  1463. }
  1464. SHAR_EOF
  1465. #    End of shell archive
  1466. exit 0
  1467. -- 
  1468. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  1469. Have five nice days.
  1470.